package com.xiaohai.big_event_system.controller;


import com.xiaohai.big_event_system.common.R;
import com.xiaohai.big_event_system.exception.CustomException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * 文件上传
 * 前端控制器
 *
 * @author xiaohai
 * @since 2023-04-02
 */
@Slf4j
@RestController
@RequestMapping("/file")
public class UploadController {
    @Value("${file.upload-dir}")
    private String path;

    /**
     * 上传文件
     *
     * @param file
     * @return
     */

    @PostMapping("/upload")
    public R<String> uploadFile(@RequestParam("file") MultipartFile file, @RequestParam(required = false, defaultValue = "false") Boolean isOriginalName) {
        try {
            // 安全文件名处理
            String originalFilename = StringUtils.cleanPath(file.getOriginalFilename()); // 获取文件名
            String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); // 获取文件后缀
            log.info("上传文件名：{},是否源文件名：{}", originalFilename, isOriginalName);
            String filename = originalFilename;
            if (!isOriginalName) {
                filename = UUID.randomUUID() + suffix; // 生成唯一文件名
            }
            // 创建外部存储目录（跨平台兼容）
            Path uploadPath = Paths.get(path).toAbsolutePath().normalize(); // 获取绝对路径
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 保存文件（使用NIO API）
            Path targetPath = uploadPath.resolve(filename);
            file.transferTo(targetPath);

            return R.success("/files/" + filename, "上传成功");
        } catch (IOException e) {
            log.error("文件上传失败：{}", e.getMessage());
            return R.error(500, "文件处理失败");
        }
    }

    /**
     * 下载文件
     *
     * @param name
     * @param response
     */
    @GetMapping("/download")
    public void download(@RequestParam String name, HttpServletResponse response) {
        try {
            Path uploadPath = Paths.get(path).toAbsolutePath().normalize();
            // 1. 获取安全存储路径
            File uploadDir = new File(String.valueOf(uploadPath)).getAbsoluteFile(); // 使用配置的独立目录
            Path filePath = uploadDir.toPath().resolve(name).normalize();

            // 2. 安全校验
            if (!filePath.startsWith(uploadDir.toPath())) {
                response.sendError(HttpStatus.FORBIDDEN.value(), "非法文件路径");
                return;
            }

            // 3. 验证文件存在性
            if (!Files.exists(filePath)) {
                response.sendError(HttpStatus.NOT_FOUND.value(), "文件不存在");
                return;
            }

            // 4. 自动识别内容类型
            String contentType = Files.probeContentType(filePath);
            response.setContentType(contentType != null ? contentType : "application/octet-stream");

            // 5. 设置下载头（处理中文文件名）
            String encodedFileName = URLEncoder.encode(name, StandardCharsets.UTF_8.name()).replace("+", "%20");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");

            // 6. 高效流式传输
            try (InputStream is = Files.newInputStream(filePath); OutputStream os = response.getOutputStream()) {
                is.transferTo(os); // Java 9+ 特性
            }

            log.info("文件下载成功: {}", name);
        } catch (IOException e) {
            throw new CustomException("文件下载失败: " + e.getMessage());
        }
    }

    /**
     * 删除文件
     *
     * @param name
     * @return
     */
    @DeleteMapping("/delete")
    public R<String> deleteFile(@RequestParam String name) {
        try {
            Path uploadPath = Paths.get(path).toAbsolutePath().normalize();
            // 1. 获取安全存储路径
            File uploadDir = new File(String.valueOf(uploadPath)).getAbsoluteFile(); // 使用配置的独立目录
            Path filePath = uploadDir.toPath().resolve(name).normalize();
            // 2. 安全校验
            if (!filePath.startsWith(uploadDir.toPath())) {
                return R.error(201, "非法文件路径");
            }
            // 3. 验证文件存在性
            if (!Files.exists(filePath)) {
                return R.error(201, "文件不存在");
            }
            // 4. 删除文件
            Files.delete(filePath);
            return R.success(null, "删除成功");

        } catch (IOException e) {
            throw new CustomException("文件删除失败: " + e.getMessage());
        }
    }
}
